/**
 * 鍓嶇鏃ュ織鐩戞帶缁勪欢
 * @author springswang
 * @date 2017-10-16
 */

!function (window) {
    'use strict';

    var oconsole = window.console; // 缂撳瓨鍘熺敓console
    var console = {};

    // console 鍏煎鎬у鐞�
    try {
        oconsole.log('DJR test console');

        // 鎺у埗鍙颁俊鎭帶鍒�
        (function () {
            var names = ['log', 'info', 'warn', 'debug', 'error'];

            for (var i = 0; i < names.length; i++) {
                console[names[i]] = (function (name) {
                    return function () {
                        if (debug) {
                            oconsole[name].apply(oconsole, Array.prototype.slice.call(arguments));
                        }
                    }
                })(names[i])
            }
        })();
    } catch (e) {
        console.log = function () {};
    }

    var debug = location.href.indexOf('debug=1') > -1 ? true : document.cookie.indexOf('DJR_DEBUG=1;') > -1 ? true : false; // 璋冭瘯妯″紡锛岄€氳繃鍙傛暟debug=1鎺у埗

    // 鏃ュ織绫诲瀷锛岄敊璇拰鑰楁椂
    var LOG_TYPE = {
        ERROR: 'err',
        COST: 'cost'
    }

    // 涓婃姤閿欒鐮�
    var ERROR_CODE = {
        JS_ERROR: -103101,
        RES_ERROR: -103102,
        XHR_ERROR: -103103
    }

    var isOnLoad = true;// 鍒氬姞杞界殑鏃跺€欙紝榛樿寤惰繜3s鍐嶄笂鎶ワ紝姝ゅ氨鐢ㄤ簬杩欎釜鍒ゆ柇

    var comboTimer = null; // 鍚堝苟涓婃姤瀹氭椂鍣�

    // 涓婃姤鍦板潃
    var logApi = location.protocol + "//logs.game.qq.com/daoju/go/frontreport/web";

    // 榛樿閰嶇疆
    var config = {
        // level: 4, // 閿欒绾у埆 1-debug 2-info 4-error
        ignore: [], // 蹇界暐鏌愪釜閿欒, 鏀寔 Regexp 鍜� Function
        location: false, // 鏄惁甯︿笂褰撳墠椤甸潰鐨剈rl,鍗曢〉搴旂敤闇€瑕佽缃负true锛屽悗鍙板彇涓嶅埌hash鍊�
        random: 1, // 鎶芥牱 (0-1] 1-鍏ㄩ噺
        delay1: 3000, // 棣栨涓婃姤寤惰繜锛岄粯璁�3s
        delay: 1000, // 浠庣浜屾涓婃姤鐨勫欢鏃讹紝榛樿寤惰繜1s涓婃姤, 涓昏鏄彲浠ュ悎骞朵笂鎶ヨ姹�
        repeat: 5, // 閲嶅涓婃姤娆℃暟(瀵逛簬鍚屼竴涓敊璇秴杩囧灏戞涓嶄笂鎶�),
        ext: '', // 鎵╁睍鍙傛暟 鐢ㄤ簬鑷畾涔変笂鎶�
        silent: {
            ALL: false,     // 鍋滄鎵€鏈変笂鎶�
            ERR: false,     // 鍋滄閿欒涓婃姤
            COST: false,    // 鍋滄鎺ュ彛鑰楁椂涓婃姤
            JS_ERR: false,  // 鍋滄JS閿欒涓婃姤
            RES_ERR: false, // 鍋滄璧勬簮閿欒涓婃姤
            XHR_ERR: false  // 鍋滄鎺ュ彛閿欒涓婃姤
        },
        onReport: function () {
        } // 涓婃姤鍥炶皟
    };

    // 宸ュ叿绫诲簱
    var util = {
        /**
         * 璁剧疆cookie
         * @param {string} sName cookie鍚�
         * @param {string} sValue cookie鍊�
         * @param {int} iExpireSec 澶辨晥鏃堕棿锛堢锛�
         * @param {string} sDomain 浣滅敤鍩�
         * @param {string} sPath 浣滅敤璺緞
         * @param {bool} bSecure 鏄惁鍔犲瘑
         * @return {void}
         */
        setCookie: function (sName, sValue, iExpireSec, sDomain, sPath, bSecure) {
            if (typeof sName == 'undefined') {
                return;
            }
            if (typeof sValue == 'undefined') {
                sValue = "";
            }

            var oCookieArray = [sName + "=" + encodeURIComponent(sValue)];
            if (!isNaN(iExpireSec)) {
                var oDate = new Date();
                oDate.setTime(oDate.getTime() + iExpireSec * 1000);
                iExpireSec == 0 ? '' : oCookieArray.push("expires=" + oDate.toGMTString());
            }
            if (sDomain != undefined) {
                oCookieArray.push("domain=" + sDomain);
            }
            if (sPath != undefined) {
                oCookieArray.push("path=" + sPath);
            }
            if (bSecure) {
                oCookieArray.push("secure");
            }
            document.cookie = oCookieArray.join("; ");
        },

        /**
         * 鑾峰彇cookie
         * @param {string} sName cookie鍚�
         * @param {string} sValue 榛樿鍊�
         * @return {string} cookie鍊�
         */
        getCookie: function (sName, sDefaultValue) {
            var sRE = "(?:; |^)" + sName + "=([^;]*);?";
            var oRE = new RegExp(sRE);

            if (oRE.test(document.cookie)) {
                return decodeURIComponent(RegExp["$1"]);
            } else {
                return sDefaultValue || null;
            }
        },

        /**
         * 璇诲彇url鍚庨潰鐨勫弬鏁�
         */
        getQuery: function (pa) {
            var url = window.location.href.replace(/#+.*$/, ''),
                params = url.substring(url.indexOf("?") + 1, url.length).split("&"),
                param = {};
            for (var i = 0; i < params.length; i++) {
                var pos = params[i].indexOf('='),//鏌ユ壘name=value
                    key = params[i].substring(0, pos),
                    val = params[i].substring(pos + 1);//鎻愬彇value
                param[key] = val;
            }
            return (typeof(param[pa]) == "undefined") ? "" : param[pa];
        },

        /**
         * 鐢熸垚鐢ㄦ埛鍞竴id,鏃堕棿鎴�+10浣嶉殢鏈烘暟
         */
        makeDeviceId: function () {
            return new Date().getTime() + '' + Math.random().toString().substr(2, 5) + '' + Math.random().toString().substr(2, 5);
        },

        /**
         * 瀵硅薄鍚堝苟
         * @param target 鐩爣瀵硅薄锛屽悗闈㈤渶瑕佸悎骞剁殑瀵硅薄锛屾敮鎸佸涓紝鍚宬ey鐨勬儏鍐碉紝鍚庨潰鐨勮鐩栧墠闈㈢殑
         * @returns {*}
         */
        extend: function (target) { // .length of function is 2

            if (target == null) { // TypeError if undefined or null
                throw new TypeError('Cannot convert undefined or null to object');
            }

            var to = Object(target);

            for (var index = 1; index < arguments.length; index++) {
                var nextSource = arguments[index];

                if (nextSource != null) { // Skip over if undefined or null
                    for (var nextKey in nextSource) {
                        // Avoid bugs when hasOwnProperty is shadowed
                        if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                            to[nextKey] = nextSource[nextKey];
                        }
                    }
                }
            }
            return to;
        },

        isType: function (o, type) {
            return Object.prototype.toString.call(o) === "[object " + (type || "Object") + "]";
        },

        isObj: function (obj) {
            var type = typeof obj;
            return type === "object" && !!obj;
        },

        isEmpty: function (obj) {
            if (obj === null) return true;
            if (util.isType(obj, "Number")) {
                return false;
            }
            return !obj;
        },

        /**
         * json瀵硅薄杞崲涓簊tring
         * @param obj json鏁版嵁瀵硅薄
         * @returns {string}
         */
        stringify: function (obj) {
            if ("undefined" != typeof JSON) {
                return JSON.stringify(obj);
            }

            // 鍏煎澶勭悊JSON杞崲string

            // 鏁扮粍杞瑂tring
            if (obj instanceof Array) {
                for (var t = [], i = 0; i < obj.length; i++) {
                    t.push(util.stringify(obj[i]));
                }

                return "[" + t.join(",") + "]";
            }

            var n = [];
            // 瀵硅薄杞瑂tring
            for (var a in obj) {
                if (obj.hasOwnProperty(a)) {
                    var str = '"' + a + '":', o = obj[a];

                    if (o) {
                        "object" == typeof o ? str += util.stringify(o) : "number" == typeof o ? str += o : str = str + '"' + o.replace(/\n/g, "\\n") + '"';
                        n.push(str)
                    }
                }
            }

            return "{" + n.join(",") + "}";
        },

        /**
         * 瑙ｆ瀽json瀛楃涓�
         * @param str json瀛楃涓�
         * @returns {*} json瀵硅薄鎴栬€卬ull
         */
        parseJSON: function (jsonStr) {
            try {
                if ("undefined" != typeof JSON) {
                    return JSON.parse(jsonStr);
                }

                return eval('(' + jsonStr + ')');
            } catch (e) {
                return null;
            }
        },

        /**
         * 鍔犺浇JS鏂囦欢锛岃繖杈瑰熀鏈兘鏄法鍩熺殑璇锋眰锛屽緢澶氭帴鍙ｉ兘璁剧疆鏀寔var xxx杩欑褰㈠紡锛�
         * 鍓嶇鍩烘湰閮芥槸鐢╯cript鏍囩鏂瑰紡澶勭悊鐨勶紝鎵€浠ヤ负浜嗙洃鎺ц繖閮ㄥ垎鎺ュ彛璁块棶鎯呭喌锛屽繀椤昏鍗曠嫭澶勭悊杩欎釜閫昏緫
         * @param url 鎺ュ彛鍦板潃
         * @param callback 鍥炶皟鍑芥暟
         * @returns {boolean}
         */
        loadScript: function (url, callback, charset) {
            var head = document.getElementsByTagName("head")[0];
            var script = document.createElement("script");
            script.type = "text/javascript";
            script.charset = typeof charset == 'undefined' ? "gb2312" : charset;
            script.src = url;

            var isImpOnLoad = ('onload' in script) ? true :
                (function(){
                    script.setAttribute('onload','');
                    return typeof script.onload == 'function' ;
                })();

            if (document.addEventListener) {
                // script 鏍囩鍔犺浇js锛屽鏋滆В鏋愰敊璇殑璇濓紝鍙兘閫氳繃window.addEventListener("error")鐩戝惉鍒�
                script.addEventListener('load', function (e) {
                    console.log('DJR load script onload', arguments);
                    // try {
                    // window.eval(e.target.innerText);
                    // Remove the script
                    if (head && script.parentNode) {
                        head.removeChild(script);
                    }
                    script = null;
                    callback && callback.call(this, e, 'success');
                    // } catch (ex) { // 杩欓噷鍙兘鐩戝惉鍒癹s鏈韩閫昏緫閿欒锛屾棤娉曠洃鍚琷s鑴氭湰瑙ｆ瀽閿欒
                    //     callback && callback.call(this, ex, ex.message || 'loadScript callback error');
                    // }
                }, false);

                // 鍙兘鍙兘鐩戝惉40X,鎴栬€�50X,杩欎釜鐩存帴閫氳繃window.addEventListener鎹曡幏
                // script.addEventListener('error', function (e) {
                //     console.log('DJR load script onerror', arguments);
                //     // Remove the script
                //     if (head && script.parentNode) {
                //         head.removeChild(script);
                //     }
                //     script = null;
                //     // callback && callback(e, '40X,50X');
                // }, false);

            } else if (!isImpOnLoad){
                script.attachEvent ('onreadystatechange', function(){
                    var rs = script.readyState.toLowerCase();
                    if (rs === 'loaded' || rs === 'complete') {
                        console.log('DJR load script onload', arguments);
                        // try {
                        // window.eval(e.target.innerText);
                        // Remove the script
                        if (head && script.parentNode) {
                            head.removeChild(script);
                        }
                        script = null;
                        callback && callback.call(this, script, 'success');
                    }
                });
            } else {
                console.log('DJR 璇锋洿鏂版祻瑙堝櫒');
            }

            head.appendChild(script);
            return script;
        },

        /**
         * 鑾峰彇dom鍏冪礌鐨剎path
         * @param e
         * @returns {string}
         */
        getXPath: function (e) {
            for (var t = []; e && e.nodeType == Node.ELEMENT_NODE; e = e.parentNode) {
                var r, n = 0, a = !1;
                for (r = e.previousSibling; r; r = r.previousSibling)r.nodeType != Node.DOCUMENT_TYPE_NODE && r.nodeName == e.nodeName && ++n;
                for (r = e.nextSibling; r && !a; r = r.nextSibling)r.nodeName == e.nodeName && (a = !0);
                var i = (e.prefix ? e.prefix + ":" : "") + e.localName, o = n || a ? "[" + (n + 1) + "]" : "";
                t.splice(0, 0, i + o)
            }
            return t.length ? "/" + t.join("/") : ''
        },

        /**
         * 鑾峰彇dom鍏冪礌鐨剆elector
         * @param e
         * @returns {string}
         */
        getSeletor: function (e) {
            for (var t = []; e.parentNode;) {
                if (e.id) {
                    t.unshift("#" + e.id);
                    break
                }
                if (e == e.ownerDocument.documentElement) t.unshift(e.tagName); else {
                    for (var r = 1, n = e; n.previousElementSibling; n = n.previousElementSibling, r++);
                    t.unshift(e.tagName + ":nth-child(" + r + ")")
                }
                e = e.parentNode
            }
            return t.join(" > ")
        },

        /**
         * 搴忓垪鍖朖SON瀵硅薄
         * 瀵筼bject杞寲涓簎rl鍙傛暟瀛楃涓诧紝鍚勫睘鎬ч棿浠�&鍒嗛殧锛屽a=1&b=2&c=3
         * 瀵硅薄灞炴€т负string 鍒欒繘琛宔ncodeURIComponent缂栫爜
         * 瀵硅薄灞炴€т负bool 鍒欎互0浠ｈ〃false 1浠ｈ〃true
         * 瀵硅薄灞炴€т负瀵硅薄锛屽垯浼氱户缁繘琛岄€掑綊搴忓垪鍖�
         * 瀵硅薄灞炴€т负function 鍒欒繑鍥瀎unction.toString
         * @param {object} jsonObj json瀵硅薄
         * @return {string}
         */
        serialize: function (jsonObj) {
            var newJsonObj = null;
            if (typeof(jsonObj) == 'undefined' || typeof(jsonObj) == 'function')
                newJsonObj = '';
            if (typeof(jsonObj) == 'number')
                newJsonObj = jsonObj.toString();
            if (typeof(jsonObj) == 'boolean')
                newJsonObj = (jsonObj) ? '1' : '0';
            if (typeof(jsonObj) == 'object') {
                if (!jsonObj) newJsonObj = '';
                if (jsonObj instanceof RegExp) newJsonObj = jsonObj.toString();
            }
            if (typeof(jsonObj) == 'string')
                newJsonObj = jsonObj;
            if (typeof(newJsonObj) == 'string')
                return encodeURIComponent(newJsonObj);

            var ret = [];
            if (jsonObj instanceof Array) {
                for (var i = 0; i < jsonObj.length; i++) {
                    if (typeof(jsonObj[i]) == 'undefined')    continue;
                    ret.push(typeof(jsonObj[i]) == 'object' ? '' : util.serialize(jsonObj[i]))
                }
                return ret.join('|')
            }
            else {
                for (var i in jsonObj) {
                    if (typeof(jsonObj[i]) == 'undefined')    continue;
                    newJsonObj = null;
                    if (typeof(jsonObj[i]) == 'object') {
                        if (jsonObj[i] instanceof Array) {
                            newJsonObj = jsonObj[i];
                            ret.push(i + '=' + util.serialize(newJsonObj));
                        } else {
                            ret.push(i + '=')
                        }
                    } else {
                        newJsonObj = jsonObj[i];
                        ret.push(i + '=' + util.serialize(newJsonObj));
                    }
                }
                return ret.join('&')
            }
        },
        /**
         * 鍙嶅簭鍒楀寲涓篔SON瀵硅薄
         * 瀵箄rl鍙傚舰褰㈠紡鐨勫璞″弽搴忓垪鍖栨垚涓篔SON瀵硅薄
         * 涓巗erialize鐩稿搴�
         * @param {object} jsonObj json瀵硅薄
         * @return {string}
         */
        unSerialize: function (jsonStr, de) {
            de = de || 0;
            jsonStr = jsonStr.toString();
            if (!jsonStr) return {};
            var retObj = {},
                obj1Ret = jsonStr.split('&');
            if (obj1Ret.length == 0) return retObj
            for (var i = 0; i < obj1Ret.length; i++) {
                if (!obj1Ret[i]) continue;
                var ret2 = obj1Ret[i].split('=');
                if (ret2.length >= 2) {
                    var ret0 = obj1Ret[i].substr(0, obj1Ret[i].indexOf('=')),
                        ret1 = obj1Ret[i].substr(obj1Ret[i].indexOf('=') + 1);
                    if (!ret1) ret1 = '';
                    if (ret0) retObj[ret0] = de == 0 ? decodeURIComponent(ret1) : ret1;
                }
            }
            return retObj;
        }
    }

    /**
     * 鏃ュ織闃熷垪锛屽彧浣滀负寤舵椂鍙戦€佺殑鏃ュ織鐨勭紦瀛橈紝鐩存帴浣跨敤鍐呭瓨鍙橀噺鏂瑰紡
     */
    var queue = {

        logs: [],

        /**
         * 澧炲姞涓€鏉℃棩蹇楀埌寰呭彂閫侀槦鍒�
         * @param log
         */
        push: function (log) {
            return this.logs.push(log);
        },

        // 鍏堣繘鍏堝嚭
        shift: function () {
            return this.logs.shift();
        },

        list: function () {
            return this.logs;
        },

        /**
         * 娓呯┖鏃ュ織缂撳瓨
         */
        clear: function () {
            this.logs = [];
        }
    }

    /**
     * 鏃ュ織涓婃姤涓讳綋鏂规硶
     */
    var logger = {

        map: {}, // 娑堟伅缂撳瓨


        init: function () {
            var that = this, onerror = window.onerror;

            // rewrite window.oerror
            window.onerror = function (msg, url, line, col, error) {
                console.log('DJR window.onerror', arguments);
                try {
                    var log = that.formatJsError(msg, url, line, col, error);

                    that.process(log);

                    onerror && onerror.apply(window, arguments);
                } catch (e) {
                }
            };

            // 鐩戞帶璧勬簮閿欒
            window.addEventListener && window.addEventListener("error", function (e) {
                try {
                    if (e && !e.message) { // 闈為敊璇秷鎭�,涓€鑸槸璧勬簮鍔犺浇404杩欓噷澶勭悊锛孞S 閿欒閮藉湪onerror閲屽鐞�
                        console.log('DJR window.addEventListener error', arguments);
                        that.formatResourceError(e, function (log) {
                            that.process(log);
                        });
                    }
                } catch (e) {}

            }, true)
        },


        /**
         * 鎻愪緵缁欏閮ㄦ墜鍔ㄨ皟鐢�,鎵嬪姩閰嶇疆
         * @param params
         */
        config: function (userConfig) {
            util.extend(config, userConfig);
        },

        /**
         * 璇诲彇涓氬姟浠ｇ爜
         */
        getBizCode: function () {
            return '';
        },

        /**
         * 璇诲彇娓犻亾id
         * @returns {string}
         */
        getAppId: function () {
            return '';
        },

        /**
         * 鑾峰彇璁惧鍞竴id
         * @returns {*|string}
         */
        getDeviceId: function () {
            var name = 'DJC_LOG_DEVICEID',
                id = util.getCookie(name);

            if (!id) {
                id = util.makeDeviceId();
                util.setCookie(name, id);
            }

            return id;
        },

        /**
         * 鏍煎紡鍖栭敊璇璞�
         * @param errObj
         * @returns {*}
         */
        formatJsError: function (msg, url, line, col, error) {
            var stack = '';

            if (error && error.stack) {
                console.log('DJR error.stack\n', error.stack);
                stack = logger.formatJsStack(error);
            }

            if (util.isType(stack, "Event")) {
                stack += stack.type ?
                    ("--" + stack.type + "--" + (stack.target ?
                        (stack.target.tagName + "::" + stack.target.src) : "")) : "";
            }

            return {
                ec: ERROR_CODE.JS_ERROR,
                msg: msg,
                target: url,
                rnum: line,
                cnum: col,
                stack: stack
            };
        },

        /**
         * 鏍煎紡鍖栧爢鏍堜俊鎭�
         * @param error
         * @returns {string}
         */
        formatJsStack: function (error) {
            var stack = error.stack
                .replace(/\n/gi, "")
                .split(/\bat\b/)
                .slice(0, 9)
                .join("@")
                .replace(/\?[^:]+/gi, "");
            var msg = error.toString();
            if (stack.indexOf(msg) < 0) {
                stack = msg + "@" + stack;
            }
            return stack;
        },

        /**
         * 鏍煎紡鍖栬祫婧愬姞杞介敊璇�
         * @param e 閿欒浜嬩欢
         */
        formatResourceError: function (e, callback) {
            var target = e.target ? e.target : e.srcElement,
                ohtml = target && target.outerHTML;
            ohtml && ohtml.length > 200 && (ohtml = ohtml.slice(0, 200));

            var report_log = {
                ec: ERROR_CODE.RES_ERROR,
                target: target && target.src,
                msg: '404 Not Found',
                stack: '',
                ext: {
                    outerHTML: ohtml,
                    tagName: target && target.tagName,
                    id: target && target.id,
                    className: target && target.className,
                    name: target && target.name,
                    type: target && target.type,
                    XPath: util.getXPath(target),
                    selector: util.getSeletor(target),
                    timeStamp: e.timeStamp
                }
            };
            // if (target.src !== window.location.href && (!target.src || !target.src.match(/.*\/(.*)$/) || target.src.match(/.*\/(.*)$/)[1]) && target.src && window.XMLHttpRequest) {
            //     try { // 澶勭悊鑷韩鐨勫紓甯告儏鍐�
            //         var xhr = new XMLHttpRequest;
            //
            //         xhr.DJ_REPORT = true;
            //         xhr.open("HEAD", target.src);
            //         xhr.send();
            //         xhr.onload = function (rsp) {
            //             if (rsp.target && 200 !== rsp.target.status) {
            //                 report_log.msg = rsp.target.status + ' ' + rsp.target.statusText;
            //                 callback && callback(report_log);
            //             }
            //         }
            //     } catch(e){ // 榛樿閮芥寜404澶勭悊
            callback && callback(report_log);
            // }
            // }
        },

        /**
         * 鏍煎紡鍖栦笂鎶ユ棩蹇楁暟鎹负query鍙傛暟鐨勫舰寮�
         * @param params 鍙傛暟
         */
        formatParams: function (params) {
            var tmp = [];

            params = util.extend({
                pf: 'web',
                md: LOG_TYPE.ERROR, //err or cost
                ts: new Date().getTime(),
                device: this.getDeviceId(),
                rf: encodeURIComponent(document.referrer),
                ch: encodeURIComponent(util.getQuery('ADTAG') || util.getQuery('CLICKTAG') || util.getQuery('ECODE')),
                biz: this.getBizCode(),
                app: this.getAppId(),
                ext: config.ext
            }, params);

            if (config.location) {
                params.url = location.href;
            }

            for (var name in params) {
                if (params.hasOwnProperty(name)) {
                    if (params[name]) {
                        tmp.push(name + '=' + (util.isObj(params[name], 'object') ? encodeURIComponent(util.stringify(params[name])) : params[name]));
                    }
                }
            }
            console.log('DJR report data:', params, tmp);
            return tmp.join('&');
        },

        /**
         * 閿欒娑堟伅鏄惁閲嶅浜�
         * @param error
         * @returns {boolean}
         */
        isRepeat: function (error) {
            var msg = error.msg,
                times = this.map[msg] = (parseInt(this.map[msg], 10) || 0) + 1;

            return config.repeat > 0 ? times > config.repeat : false; // config.repeat涓�0鐨勬椂鍊欎笉闄愬埗
        },

        /**
         * 涓婃姤涓婚€昏緫锛屽鐞嗘棩蹇椾笂鎶�
         * @param log 鏂板閿欒鏃ュ織
         */
        process: function (report_log) {
            // 閬垮厤鑷敓閫昏緫鎶ラ敊褰卞搷姝ｅ父涓氬姟閫昏緫
            try {
                var userReport = true, data = report_log;

                // 娉ㄦ剰鍚庨潰瀵筩ost鐨勫垽鏂紝浣跨敤浜唀nd锛屽洜涓烘湰韬玞ost鏁版嵁閲岄潰涔熸湁cost瀛楁锛岀敤鏉ユ爣璇嗚€楁椂鐨勶紝鍐茬獊浜嗭紝鎵€浠ヨ繖閲屾敼涓篹nd缁撴潫鏃堕棿鏉ュ垽鏂�
                report_log = report_log.err ? report_log.err : (!report_log.ec && !report_log.end ? report_log.cost : (userReport = false, data = {}, report_log));

                // 鎶芥牱浣跨敤闅忔満鏁板鐞�
                var isCost = report_log.ec ? false : true, // 鑰楁椂缁熻
                    randomIgnore = Math.random() >= config.random;

                // 鏈夋晥淇濊瘉瀛楃涓嶈杩囬暱
                if (!isCost) { // 鑰楁椂鏃ュ織涓嶈蛋涓嬮€昏緫锛屽彧鏈夐敊璇棩蹇楁墠澶勭悊
                    // 閲嶅涓婃姤
                    if (this.isRepeat(report_log)) {
                        return false;
                    }
                    // 娑堟伅瓒呴暱鎴柇
                    report_log.msg = (report_log.msg + "" || "").substr(0, 500);

                    var log_str = util.stringify(report_log);

                    console.log('DJR log_str:' ,log_str);

                    // 閿欒鏃ュ織蹇界暐鍖归厤
                    if (util.isType(config.ignore, "Array")) {
                        for (var i = 0, l = config.ignore.length; i < l; i++) {
                            var rule = config.ignore[i];
                            if ((util.isType(rule, "RegExp") && rule.test(log_str)) ||
                                (util.isType(rule, "Function") && rule(log_str))) {
                                return false;
                            }
                        }
                    }
                }

                if (!randomIgnore) {

                    if (!userReport && (isOnLoad || config.delay > 0)) {

                        if (isOnLoad) {
                            // 棣栨涓婃姤寤舵椂鏍囪瘑澶勭悊
                            setTimeout(function () {
                                isOnLoad = false;
                            }, config.delay1);
                        }

                        queue.push(report_log);

                        if (!comboTimer) {
                            comboTimer = setTimeout(function () {
                                comboTimer = 0;
                                logger.batch();
                            }, isOnLoad ? config.delay1 : config.delay);
                        }
                    } else {

                        if (report_log.ec) {
                            this.submit(util.extend(data, {
                                md: LOG_TYPE.ERROR,
                                err: [report_log]
                            }));
                        } else {
                            this.submit(util.extend(data, {
                                md: LOG_TYPE.COST,
                                cost: [report_log]
                            }));
                        }
                    }

                    config.onReport && (config.onReport(report_log));
                }
            } catch (e) {
            }
        },

        /**
         * 鎻愪緵缁欏閮ㄦ墜鍔ㄨ皟鐢�
         * @param params
         */
        report: function (params) {
            logger.process.call(logger, params);
        },

        /**
         * 鎵归噺涓婃姤锛屼富瑕佺敤浜庡欢鏃朵笂鎶�
         */
        batch: function () {
            var log, errs = [], tcs = [];

            while (log = queue.shift()) {
                if (log.ec) { // 閿欒鏃ュ織
                    errs.push(log);
                } else { // 鎺ュ彛鑰楁椂
                    tcs.push(log);
                }
            }

            if (errs.length > 0) {
                this.submit({
                    md: LOG_TYPE.ERROR,
                    err: errs
                });
            }

            if (tcs.length > 0) {
                this.submit({
                    md: LOG_TYPE.COST,
                    cost: tcs
                });
            }
        },

        /**
         * 鍙戦€佹棩蹇�
         * @param t
         */
        submit: function (log) {
            var data = this.formatParams(log);

            // this.buildFrom(this.buildIFrame(), data).submit();
            // return false;
            if (data) {
                try {
                    // 瀛樺湪XMLHttpRequest 鐩存帴浣跨敤瀹働OST鏃ュ織,鏈夎法鍩熺殑闂
                    if (data.length < 1000) { // 涓嶅瓨鍦ㄥ氨鐩存帴img鏍囩鍙戦€佽姹�
                        var img = new Image;

                        img.onload = img.onerror = function () {
                            img = null;
                        }

                        img.src = logApi + "?" + data;
                        console.log('DJR submit way: IMG');
                    } else {
                        if (window.XMLHttpRequest) {
                            var xhr = new XMLHttpRequest;

                            if ('withCredentials' in xhr) {
                                xhr.open("POST", logApi);

                                xhr.withCredentials = true;
                                xhr.DJ_REPORT = true;

                                xhr.send(data);
                                console.log('DJR submit way: XHR');
                            } else if (window.XDomainRequest) {
                                xhr = new XDomainRequest;
                                xhr.DJ_REPORT = true;

                                xhr.open("POST", logApi);
                                xhr.send(data);
                                console.log('DJR submit way: XDR');
                            } else {
                                this.buildFrom(this.buildIFrame(), data).submit();
                                console.log('DJR submit way: IFR');
                            }
                        }
                    }
                } catch (e) {
                }
            }
        },

        /**
         * 鏋勫缓iframe
         * @returns {*}
         */
        buildIFrame: function () {
            var ifr = document.getElementsByName("djreport_iframe");

            if (ifr.length == 0) {
                var iframe = document.createElement("iframe");
                iframe.name = "djreport_iframe";
                iframe.frameborder = 0;
                iframe.height = 0;
                iframe.width = 0;
                iframe.src = "about:blank";

                document.body.appendChild(iframe);
                return iframe;
            }

            return ifr[0]
        },

        /**
         * 鏋勫缓涓€涓猣orm琛ㄥ崟
         * @param ifr
         * @param data
         * @returns {NodeList}
         */
        buildFrom: function (ifr, data) {
            var params = data.split('&'),
                form = document.getElementsByName("djreport_form");

            if (form.length == 0) {
                var form = document.createElement("form");
                form.name = "djreport_form";
                form.style.display = "none";
                form.target = ifr.name;
                form.method = "POST";
                form.action = logApi;
                form.enctype = 'multipart/form-data';
            } else {
                form = form[0];
            }

            for (var i = 0, len = params.length; i < len; i++) {
                var kv = params[i].split('='), input;
                console.log('DJR input', kv[0]);
                if (!form[kv[0]]) {
                    input = document.createElement("input")
                    input.type = "hidden";
                    form.appendChild(input);
                } else {
                    input = form[kv[0]];
                }
                input.name = kv[0];
                input.value = kv[1];
            }

            document.body.appendChild(form);

            return form;
        }

    }


    /**
     * 鎺ュ彛鐩戞帶涓昏閫昏緫
     * @type {{}}
     */
    var monitor = {

        init: function () {
            this.wrapXHR();
            // this.wrapFetch();
            this.wrapScript();
        },

        /**
         * xhr灏佽锛岀洃鎺ц姹傛帴鍙�
         */
        wrapXHR: function () {
            if (window.XMLHttpRequest) {
                var XHR = XMLHttpRequest.prototype;

                if (!XHR) return false;

                var startTime, _open = XHR.open, _send = XHR.send;

                // 灏佽XHR鐨刼pen鏂规硶锛屼互渚胯褰曟椂闂�
                XHR.open = function (mthd, uri) {
                    this.DJR_URL = uri; // 涓存椂瀛樺偍锛屼究浜庢棩蹇椾笂鎶ヨ幏鍙栧綋鍓峹hr鐨剈rl
                    this.DJR_METHOD = mthd; // 涓存椂瀛樺偍锛屼究浜庢棩蹇椾笂鎶ヨ幏鍙栧綋鍓峹hr鐨凪ETHOD
                    this.DJR_STARTTIME = (new Date).getTime();

                    try {
                        _open.apply(this, arguments)
                    } catch (e) {
                        var logData = {
                            ec: ERROR_CODE.XHR_ERROR,
                            msg: 'XHROpenError:' + e.message,
                            target: uri,
                            method: method.toUpperCase() || 'GET '
                            // rnum: '',
                            // cnum: '',
                            // stack: ''
                        }

                        logger.process(logData);
                    }
                };

                // 灏佽XHR鐨剆end鏂规硶锛屼互渚胯褰曡€楁椂
                XHR.send = function (query) {
                    var that = this,
                        method = this.DJR_METHOD,
                        url = !!this.DJR_URL ? that.DJR_URL : !!that.responseURL ? that.responseURL : '',
                        _onreadystatechange = that.onreadystatechange;

                    // jquery鐨刟jax璇锋眰鏄悗璁剧疆onreadystatechange鐨勶紝浼氳鐩栬繖閲岀殑瀹氫箟
                    // 杩欓噷鐢╯etTimeout鎶婃墽琛屾斁鍒颁笅涓€涓墽琛屽垏鐗囬噷锛屽凡杈惧埌鍦╦Query璁剧疆浜唎nreadystatechange涔嬪悗鍐嶈缃畠
                    setTimeout(function () {
                        that.onreadystatechange = function () {
                            // 閬垮厤鑷敓閫昏緫鎶ラ敊褰卞搷姝ｅ父涓氬姟閫昏緫
                            try {
                                if (4 === that.readyState && !that.DJ_REPORT && url.indexOf(logApi) < 0) {
                                    var endTime = (new Date).getTime(), diffTime = endTime - that.DJR_STARTTIME;

                                    if (that.status == 200) { // 闈�200锛岃蛋閿欒鏃ュ織
                                        var logData = {
                                            url: url, //  detail: {method: X, url: t.responseURL || C, status: t.status, statusText: t.statusText},
                                            param: query ? query : '',
                                            start: startTime,
                                            end: endTime,
                                            cost: diffTime,
                                            method: method.toUpperCase() || 'GET'
                                        }
                                    } else {
                                        var logData = {
                                            ec: ERROR_CODE.XHR_ERROR,
                                            msg: 'XHRSendError:' + that.status,
                                            target: url + util.isType(query, 'Object') ? '?' + util.serialize(query) : util.isType(query, 'String') ? '?' + query : '',
                                            method: method.toUpperCase() || 'GET'
                                            // rnum: '',
                                            // cnum: '',
                                            // stack: ''
                                        }
                                    }
                                    // 閽堝娴忚鍣╝bort鐨勬儏鍐碉紝灏变笉涓婃姤浜�
                                    if(that.status != 0 ){
                                        logger.process(logData);
                                    }

                                    // f(a)
                                }
                            } catch (e) {
                            }

                            _onreadystatechange && _onreadystatechange.apply(this, arguments);
                        };
                    }, 0);

                    _send.apply(this, arguments);
                }
            }
        },

        // /**
        //  * 灏佽Fetch鏂规硶
        //  */
        // wrapFetch: function () {
        //     if (window.fetch) {
        //         var _fetch = window.fetch;
        //         window.fetch = function (request, params) {
        //             var startTime = (new Date).getTime();
        //
        //             return _fetch.apply(this, arguments).then(function (rsp) {
        //                 var endTime = (new Date).getTime(), diffTime =  endTime - startTime;
        //
        //                 if(rsp.status == 200){ // 闈�200锛岃蛋閿欒鏃ュ織
        //                     var logData = {
        //                         url: rsp.url, //  detail: {method: X, url: t.responseURL || C, status: t.status, statusText: t.statusText},
        //                         param: params.body,
        //                         start: startTime,
        //                         end: endTime,
        //                         cost: diffTime,
        //                         method: rsp.headers.method ? rsp.headers.method.toUpperCase() : 'GET'
        //                     }
        //                 } else {
        //                     var logData = {
        //                         ec: ERROR_CODE.XHR_ERROR,
        //                         msg: 'FetchError:' + rsp.status,
        //                         target: rsp.url + '?' + params.body,
        //                         method: rsp.headers.method ? rsp.headers.method.toUpperCase() : 'GET'
        //                         // rnum: '',
        //                         // cnum: '',
        //                         // stack: ''
        //                     }
        //                 }
        //
        //                 logger.process(logData);
        //             })
        //         }
        //     }
        // },

        /**
         * 灏佽script鏂瑰紡璇锋眰鏁版嵁
         */
        wrapScript: function () {
            var _ajax,          // 缂撳瓨jQuery.ajax鏂规硶
                _getScript,     // 缂撳瓨jQuery.getScript鏂规硶
                _loadScript;    // 缂撳瓨milo.loader.getScript鍜寃indow.getScript

            // 瀹炵幇灏佽
            var ajaxScript = function (host, url, _callback, options) {
                var startTime = (new Date).getTime();

                try {
                    url = new URL(url, location.href).href;
                } catch (e) {

                }

                var callback = function (jqxhr, statusText) {
                    var endTime = (new Date).getTime(), diffTime = endTime - startTime;

                    if (statusText == 'success') {
                        var logData = {
                            url: url + (options && options.data ? '?'+util.serialize(options.data) : ''),
                            param: '',
                            start: startTime,
                            end: endTime,
                            cost: diffTime,
                            method: 'GET'
                        }
                        _callback && _callback(true, jqxhr, statusText);
                    } else {
                        var logData = {
                            ec: ERROR_CODE.XHR_ERROR,
                            msg: 'LoadScriptError:' + statusText,
                            target: url + (options && options.data ? '?'+util.serialize(options.data) : ''),
                            method: 'GET'
                            // rnum: '',
                            // cnum: '',
                            // stack: ''
                        }
                        _callback && _callback(false, jqxhr, statusText);
                    }
                    logger.process(logData);
                };

                if (host == 'jQuery') {

                    if (options && options.dataType && /(JSONP|SCRIPT)/gi.test(options.dataType)) { // 澶勭悊SCRIPT鍜孞SONP

                        // jsonp鐨勬垚鍔熻繑鍥炲€间笉涓€鏍凤紝鏄痙ata锛岃€屽け璐ヨ繑鍥炵殑jqxhr锛岃繖閲岄渶瑕佹敞鎰�
                        options.success = function (data) {
                            callback(data, 'success');
                        };

                        // options.complete = function (jqxhr, statusText) {
                        //     if (statusText != 'success') {
                        //         callback(jqxhr, statusText);
                        //     }
                        // };
                    } else {
                        if(!!_callback) {
                            options= {
                                success: function (jxhr) {
                                    callback(jxhr, 'success');
                                }
                            };
                        }
                    }

                    var xhr = _getScript(util.extend({
                        type: 'get',
                        url: url,
                        dataType: 'script',
                        crossDomain: true
                    }, options || {}));

                    console.log('DJR _getScript options', options);

                    if (xhr && typeof xhr['complete'] == 'function') {  // promise鏍峰紡璋冪敤鍏煎澶勭悊
                        var funcs = ['then', 'done', 'success', 'fail', 'error', 'complete'],
                            funcWraps = {};

                        // 灏佽$.getScript鐨刾romise鏍峰紡鐨勬帴鍙�
                        for (var i = 0, len = funcs.length; i < len; i++) {
                            var func = funcs[i];

                            if (typeof xhr[func] == 'function') {
                                funcWraps[func] = xhr[func];

                                xhr[func] = function (xhr, func) { // 闂寘淇濆瓨xhr func鍙橀噺
                                    return function (cb) {
                                        console.log('DJR xhr promise wrap', func, url, funcWraps[func], cb);
                                        return funcWraps[func].call(xhr, cb);
                                    }
                                }(xhr, func);
                            }
                        }
                        !_callback && funcWraps['complete'](callback);
                    }

                    return xhr;

                } else if (host == 'milo') {
                    return _loadScript(url, callback);
                }
            }

            var checkWrapTimer;

            // 瀹氭椂鍣紝妫€娴媠cript鏂规硶
            var checkWrap = function () {

                if (window.jQuery) {
                    // jQuery鐨刟jax鏂规硶鍖呭３
                    if (typeof $.ajax == 'function' && !$.__ajaxWrap__) {
                        _ajax = $.ajax;

                        $.ajax = function (url, options) {

                            options = options || {};

                            if(typeof url === "string" ){
                                options.url = url;
                            } else if ( typeof url === "object" ) {
                                options = url;
                            }

                            // Force options to be an object


                            // 澶勭悊$.ajax涓璬ataType = SCRIPT|JSONP 鐨勮姹�
                            if (options && options.dataType && /(JSONP|SCRIPT)/gi.test(options.dataType)) {
                                var _success = options.success,
                                    _error = options.error,
                                    _complete = options.complete;

                                delete options.success;
                                delete options.error;
                                delete options.complete;

                                return ajaxScript('jQuery', options.url, function (isSuccess, jqxhr, statusText) {
                                    //  ajax 鎬诲叡鏈� error銆乻uccess銆乧omplete 涓変釜缁撴潫鍥炶皟鏂规硶锛岄兘瑕佸鐞�
                                    if (isSuccess) {
                                        if (typeof _success == 'function') {
                                            _success(jqxhr, statusText);
                                        }
                                    } else {
                                        if (typeof _error == 'function') {
                                            _error(jqxhr, statusText);
                                        }
                                    }

                                    if (typeof _complete == 'function') {
                                        _complete(jqxhr, statusText);
                                    }
                                }, options);
                            } else {
                                return _ajax(options);
                            }
                        }

                        $.__ajaxWrap__ = true;
                    }

                    // jQuery鐨刧etScript鏂规硶鍖呭３
                    if (typeof $.getScript == 'function' && !$.__getScriptWrap__) {
                        _getScript = _ajax;

                        $.getScript = function (url, callback) {

                            if(typeof callback == 'function'){
                                return ajaxScript('jQuery', url, callback);
                            } else { // callback 涓嶅瓨鍦ㄧ殑鏃跺€欙紝璋冪敤鏂瑰紡鏄痯romise鏂瑰紡
                                return ajaxScript('jQuery', url, null);
                            }
                        }

                        $.__getScriptWrap__ = true;
                    }
                }
                // milo宸茬粡鑷畾涔夌殑loadScript鏂规硶鍖呭３
                if (typeof loadScript == 'function' && !window.__loadScriptWrap__) {
                    _loadScript = util.loadScript;

                    window.loadScript = function (url, callback) {
                        return ajaxScript('milo', url, callback);
                    }

                    window.__loadScriptWrap__ = true;
                }

                if ((window.$ && $.__getScriptWrap__) && window.__loadScriptWrap__) {
                    return false;
                }
                // 杞妫€娴�
                checkWrapTimer = setTimeout(checkWrap, 100);
            }
            // 杞15s鍚庯紝鍙栨秷锛岄槻姝query鏄悗load鐨勶紝涓€鑸�15s jquery 90%浠ヤ笂鐨勫嚑鐜囬兘浼氬姞杞藉畬鎴愪簡
            setTimeout(function () {
                clearTimeout(checkWrapTimer);
            }, 15000);

            checkWrap();
        }
    }

    logger.init();
    monitor.init();

    window.DJ_REPORT = {
        config: logger.config,
        report: logger.report
    }
    https://app.daoju.qq.com/act/a20170809lucky/index.htm?plat_support=mqq&debug=1
    DJ_REPORT.config({
        ignore: [/(src=\\"\\"|about:blank|tajs\.qq\.com|pingjs\.qq\.com|pingfore\.qq\.com|logs\.game\.qq\.com|jqmt\.qq\.com|sCloudApiName=atm)/i] // 澶撮儴鐨勭敤鎴穒con鏄悗璁剧疆鐨勶紝杩欎釜涓嶅鐞�
    });

    // 娴嬭瘯杈撳嚭鍐呴儴瀵硅薄
    if (debug) {
        window.DJ_REPORT = util.extend(window.DJ_REPORT, {
            conf: config,
            util: util,
            logger: logger,
            monitor: monitor
        });
    }

}(window);

if ("undefined" != typeof milo) { // milo 鍏煎
    //TODO 鍚庣画琛ュ厖milo鐨勬ā鍧楀寲
    // var define = typeof defineconflict == 'function' ? defineconflict : (typeof define == 'function' ? define : function () {});
    //
    // define('daoju.hx.report', [], function () {
    //     return DJ_REPORT;
    // });
} else if ("function" == typeof define) { // AMD鍏煎
    define(DJ_REPORT);
} else if ("undefined" != typeof module && module.exports) { // commonJS 妯″潡鍏煎
    module.exports = DJ_REPORT;
}